package com.wsyu.springbootbackend.core.auth.filter;

import com.wsyu.springbootbackend.core.util.HttpServletUtils;
import com.wsyu.springbootbackend.core.util.JsonBuilder;
import com.wsyu.springbootbackend.core.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

@Slf4j
public class CustomJwtFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        // 请求头中获得 jwt-token-string
        String jwtTokenStr = request.getHeader("x-jwt-token");

        // 无条件放行情况一
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            log.info("Security Context 中已有 Authentication Token");
            filterChain.doFilter(request, response);
            return;
        }

        // 无条件放行情况二
        if (StringUtils.isBlank(jwtTokenStr)) {
            filterChain.doFilter(request, response);
            return;
        }

        boolean verify = JwtUtils.verify(jwtTokenStr);
        if (!verify) {
            String json = JsonBuilder.create()
                    .add("code", 400)
                    .add("msg", "jwt-token 非法，请重新的登录")
                    .build();
            HttpServletUtils.writeJsonResponse(response, HttpStatus.OK, json);
            return;
        }

        // 向 spring-security 上下文中存入 authentication-token
        // 从 jwtToken 中"抠"出用户名
        String username = JwtUtils.getUsername(jwtTokenStr);
        Authentication token = new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());
        SecurityContextHolder.getContext().setAuthentication(token);

        filterChain.doFilter(request, response);
    }
}